package org.friping.mytool.views;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.ListView;
import android.widget.TextView;

import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.Bean;
import org.androidannotations.annotations.Click;
import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.Extra;
import org.androidannotations.annotations.ItemClick;
import org.androidannotations.annotations.OnActivityResult;
import org.androidannotations.annotations.ViewById;
import org.friping.mytool.R;
import org.friping.mytool.dao.UnitDao;
import org.friping.mytool.entity.Unit;
import org.friping.mytool.helper.ActivityHelper;
import org.friping.mytool.helper.Constants;
import org.friping.mytool.helper.EntityConverter;
import org.friping.mytool.helper.JsonHelper;
import org.friping.mytool.helper.UITypeHelper;
import org.friping.mytool.views.custom.adapter.EditAdapter;

import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;

@EActivity(R.layout.a_unit_edit)
public class UnitEditActivity extends AppCompatActivity {

    @ViewById
    Toolbar toolbar;

    @ViewById
    ListView listView;

    @ViewById
    TextView showUnitBudgets;

    @Bean
    EditAdapter listViewAdapter;

    Map<String, Integer> namePos;

    List<Map> items;

    @Extra
    Long unitId;

    @Bean
    UITypeHelper uiTypeHelper;

    @Bean
    EntityConverter entityConverter;

    @Bean
    JsonHelper jsonHelper;

    @Bean
    ActivityHelper activityHelper;

    @Bean
    UnitDao unitDao;

    @AfterViews
    public void afterView(){
        setSupportActionBar(toolbar);
        initListView();
    }

    @ItemClick
    public void listViewItemClicked(int position){
        Map itemObj = (Map) listViewAdapter.getItem(position);
        String type = (String) itemObj.get("type");
        String label = (String) itemObj.get("label");
        String name = (String) itemObj.get("name");
        Bundle info = new Bundle();
        info.putString("name", name);
        info.putString("label", label);
        Object value = itemObj.get("value");
        if(name.equals("dayOfMonth")){
            Boolean isLunar = Boolean.TRUE.equals(items.get(namePos.get("isLunar")).get("value"));
            info.putBoolean("isLunar", isLunar);
        }
        uiTypeHelper.showByType(this, type, value, info);
    }

    @Click(R.id.btnSave)
    public void save(){
        Map values = uiTypeHelper.getValuesForEntity(items);

        Unit u = entityConverter.mapToEntity(new Unit(), values);
        if(unitId != null){
            unitDao.update(u, unitId);
        }else{
            unitDao.create(u);
        }

        Intent intent=new Intent();
        intent.putExtra("name", u.getName());
        setResult(Constants.EDIT_UNIT_RESULT_CODE,intent);
        finish();
    }

    @Click(R.id.showUnitBudgets)
    public void showUnitBudgets(){
        Intent intent = activityHelper.buildIntent(this, UnitBudgetListActivity_.class);
        intent.putExtra("unitId", unitId);
        startActivity(intent);
    }


    @OnActivityResult(Constants.PICKER_REQUEST_CODE)
    void onResult(int resultCode, Intent data) {
        switch (resultCode){
            case Constants.PICKER_TEXT_RESULT_CODE:
                int pos = namePos.get(data.getStringExtra("name"));
                Map itemObj = (Map) listViewAdapter.getItem(pos);
                itemObj.put("displayValue", data.getStringExtra("value"));
                itemObj.put("value", data.getStringExtra("value"));
                break;
            case Constants.PICKER_CURRENCY_RESULT_CODE:
                pos = namePos.get(data.getStringExtra("name"));
                itemObj = (Map) listViewAdapter.getItem(pos);
                itemObj.put("displayValue", data.getStringExtra("value"));
                itemObj.put("value", uiTypeHelper.fromString(UITypeHelper.Type.Currency, data.getStringExtra("value")));
                break;
            case Constants.PICKER_NOTE_RESULT_CODE:
                pos = namePos.get(data.getStringExtra("name"));
                itemObj = (Map) listViewAdapter.getItem(pos);
                itemObj.put("displayValue", data.getStringExtra("value"));
                itemObj.put("value", data.getStringExtra("value"));
                break;

            case Constants.PICKER_SWITCH_RESULT_CODE:
                pos = namePos.get(data.getStringExtra("name"));
                itemObj = (Map) listViewAdapter.getItem(pos);
                itemObj.put("displayValue", uiTypeHelper.getDisplayValue(UITypeHelper.Type.Boolean, data.getBooleanExtra("value", false)));
                itemObj.put("value", data.getBooleanExtra("value", false));

                changeDayOfMonthText(null);
                // FIXME: not sure need this here, but not for others
                listViewAdapter.notifyDataSetChanged();

                break;

            case Constants.PICKER_DATE_RESULT_CODE:
                pos = namePos.get(data.getStringExtra("name"));
                itemObj = (Map) listViewAdapter.getItem(pos);
                itemObj.put("displayValue", uiTypeHelper.getDisplayValue(UITypeHelper.Type.Date, data.getSerializableExtra("value")));
                itemObj.put("value", data.getSerializableExtra("value"));
                // FIXME: not sure need this here, but not for others
                listViewAdapter.notifyDataSetChanged();

                break;

            case Constants.PICKER_DAY_OF_MONTH_RESULT_CODE:
                pos = namePos.get(data.getStringExtra("name"));
                itemObj = (Map) listViewAdapter.getItem(pos);
                Integer value = data.getIntExtra("value", -1);
                itemObj.put("value", value);
                changeDayOfMonthText(itemObj);
                // FIXME: not sure need this here, but not for others
                listViewAdapter.notifyDataSetChanged();

                break;
        }
    }

    private void initListView() {
        items = jsonHelper.readListFromAssets(this, "unit_edit_fields.json");

        // render for update
        renderUpdate();

        AtomicInteger counter = new AtomicInteger();
        namePos = items.stream().collect(toMap(s -> (String) s.get("name"), i -> counter.getAndIncrement()));

        items = wrapItemsData(items);
        listViewAdapter.refresh(items);
        listView.setAdapter(listViewAdapter);

    }

    private List<Map> wrapItemsData(List<Map> items){
        for(Map<String, Object> item : items){
            String type = (String) item.get("type");
            Object value = item.getOrDefault("default", null);
            item.put("value", value);
            item.put("displayValue", uiTypeHelper.getDisplayValue(UITypeHelper.Type.valueOf(type), value));
            if(UITypeHelper.Type.valueOf((String) item.get("type")) == UITypeHelper.Type.DayOfMonth){
                changeDayOfMonthText(item);
            }
        }
        return items;
    }

    private void changeDayOfMonthText(Map item){
        Map dayOfMonthItem = item == null ? (Map) listViewAdapter.getItem(namePos.get("dayOfMonth")) : item;
        Boolean isLunar = Boolean.TRUE.equals(items.get(namePos.get("isLunar")).get("value"));
        Integer value = (Integer)dayOfMonthItem.get("value");
        if(value == 31 && isLunar){
            value = 30;
        }
        dayOfMonthItem.put("value", value);
        dayOfMonthItem.put("displayValue", uiTypeHelper.dayOfMonthText(value, isLunar));
    }

    private void renderUpdate(){
        if(unitId == null){
            return;
        }

        Unit unit = (Unit) unitDao.get(Unit.class, unitId);
        Map unitMap = entityConverter.entityToMap(unit);
        items = items.stream().map(item -> {
            String name = (String) item.get("name");
            item.put("default", unitMap.get(name));
            return item;
        }).collect(toList());

        showUnitBudgets.setVisibility(View.VISIBLE);
    }
}
